import {DefaultFlowModel} from '@/components/flow/DefaultFlowDefinition';
import {isEmpty, isNotEmpty} from '@/utils/CommonUtils';

export default class {
  flowImageHistory = {
    activeNodes: [],
    passedNodes: []
  };

  flowModel = DefaultFlowModel;
  res = DefaultFlowModel;

  constructor(flowImageHistory, flowModel) {
    this.flowImageHistory = flowImageHistory;
    this.flowModel = flowModel;
    this.res = JSON.parse(JSON.stringify(DefaultFlowModel));
    this.res.lines = [];
    this.res.nodes = [];
  }

  parse() {
    this.prepare();

    this.resolvePassedPath();
    this.resolveNoPassedPath();
    this.res.gatewayPairs = this.flowModel.gatewayPairs;
    this.resolveActiveClass();
    this.trySortLines();
    return this.res;
  }

  prepare() {
    let lines = this.flowModel.lines;
    let nodes = this.flowModel.nodes;
    lines.forEach(l => {
      delete l.className;
    });

    nodes.forEach(n => {
      delete n.className;
    });
  }

  resolveActiveClass() {
    let nodes = this.res.nodes;
    if (isEmpty(nodes)) return;
    let activeNodes = this.flowImageHistory.activeNodes;
    if (isEmpty(activeNodes)) activeNodes = [];

    nodes.forEach(node => {
      if (isNotEmpty(activeNodes.find(id => id === node.id))) {
        node.className = 'common-node-active';
      }
    });
  }

  trySortLines() {
    try {
      this.res.lines = this.res.lines.sort((l1, l2) => {
        let order1 = this.flowModel.lines.findIndex(l => l.id === l1.id);
        let order2 = this.flowModel.lines.findIndex(l => l.id === l2.id);
        return order1 - order2;
      });
    } catch (e) {
    }
  }

  resolveNoPassedPath() {
    let list = [...this.flowImageHistory.activeNodes, ...this.flowImageHistory.passedNodes], list1 = [];
    do {
      list1 = [];
      list.forEach(startNodeId => {
        let lines = this.getLinesByStartNodeId(startNodeId);

        let nodes = this.getLineEndNodes(lines);

        list1.push(...nodes);
        this.res.lines.push(...lines);
      });

      this.res.nodes.push(...list1);
      list = list1.map(n => n.id);
    } while (isNotEmpty(list));
  }

  getLinesByStartNodeId(startNodeId) {
    return this.flowModel.lines.filter(l => l.start === startNodeId);
  }

  getLineEndNodes(lines) {
    return this.flowModel.nodes.filter(node => !!lines.find(l => l.end === node.id));
  }

  resolvePassedPath() {
    let {lines} = this.flowModel;
    if (isEmpty(lines)) lines = [];
    for (let i = 0; i < lines.length; i++) {
      let line = lines[i];
      if ((this.isPassedNode(line.start) && !this.isActiveNode(line.start)) && this.isPassedNode(line.end)) {
        this.addLine(line);
      }
    }

    let {nodes} = this.flowModel;
    if (isEmpty(nodes)) nodes = [];
    for (let i = 0; i < nodes.length; i++) {
      let node = nodes[i];
      if (this.isPassedNode(node.id)) {
        this.addNode(node);
      }
    }
  }

  addLine(line) {
    let temp = this.res.lines.find(l => l.start === line.start && l.end === line.end);
    if (isEmpty(temp)) {
      line.className = 'line-passed';
      this.res.lines.push(line);
    }
  }

  addNode(node) {
    let temp = this.res.nodes.find(n => n.id === node.id);
    if (isEmpty(temp)) {
      if (node.type === 'gateway') {
        node.className = 'gateway-node-passed';
      } else {
        node.className = 'common-node-passed';
      }
      this.res.nodes.push(node);
    }
  }

  isActiveNode(nodeId) {
    let list = [...this.flowImageHistory.activeNodes];
    let id = list.find(id => id === nodeId);
    return isNotEmpty(id);
  }

  isPassedNode(nodeId) {
    let list = [...this.flowImageHistory.activeNodes, ...this.flowImageHistory.passedNodes];
    let id = list.find(id => id === nodeId);
    return isNotEmpty(id);
  }
}
